#include "threadsafetriangle.h"

bool ThreadSafeTriangle::invariante() const{
	return Triangle::invariante();
}

ThreadSafeTriangle::ThreadSafeTriangle()
{
	assert(0);
}

ThreadSafeTriangle::~ThreadSafeTriangle(){
}

ThreadSafeTriangle::ThreadSafeTriangle(const Triangle &t) : Triangle(t){
	assert(invariante());
}

ThreadSafeTriangle::ThreadSafeTriangle(ThreadSafeTriangle &t){
	id = t.getId();
	vertexs[0] = t.getVertex(0);
	vertexs[1] = t.getVertex(1);
	vertexs[2] = t.getVertex(2);
	neighbors[0] = t.getNeighbor(0);
	t.getMutex()->unlock();
	neighbors[1] = t.getNeighbor(1);
	t.getMutex()->unlock();
	neighbors[2] = t.getNeighbor(2);
	t.getMutex()->unlock();
	assert(invariante());
}

int ThreadSafeTriangle::longestEdgeIndex() const{
	QMutexLocker locker(&internalMutex);
	return Triangle::longestEdgeIndex();
}

int ThreadSafeTriangle::getId() const{
	QMutexLocker locker(&internalMutex);
	return id;
}

void ThreadSafeTriangle::setID(int _id) {
	QMutexLocker locker(&internalMutex);
	id = _id;
	assert(invariante());
}

Edge ThreadSafeTriangle::getEdge(int i) const{
	assert(i<3&&i>-1);
	QMutexLocker locker(&internalMutex);
	return Edge(vertexs[(i+1)%3],vertexs[(i+2)%3]);
}

Vertex* ThreadSafeTriangle::getVertex(int i) const{
	assert(i<3&&i>-1);
	QMutexLocker locker(&internalMutex);
	return vertexs[i];
}

bool ThreadSafeTriangle::hasEdge(const Edge *e) const{
	QMutexLocker locker(&internalMutex);
	return Triangle::hasEdge(e);
}

std::string ThreadSafeTriangle::toString() const {
	QMutexLocker locker(&internalMutex);
	return Triangle::toString();
}

void ThreadSafeTriangle::setNeighbors(ThreadSafeTriangle *t1, ThreadSafeTriangle *t2, ThreadSafeTriangle *t3){
	QMutexLocker locker(&internalMutex);
	neighbors[0] = t1;
	neighbors[1] = t2;
	neighbors[2] = t3;
	assert(invariante());
	neighborChanged.wakeAll();
}

void ThreadSafeTriangle::setNeighbor(int index, ThreadSafeTriangle *n){
	assert(index>-1&&index<3);
	QMutexLocker locker(&internalMutex);
	neighbors[index]=n;
	assert(invariante());
	neighborChanged.wakeAll();
}

void ThreadSafeTriangle::replaceNeighbor(ThreadSafeTriangle *objective,ThreadSafeTriangle *replacement){
	QMutexLocker locker(&internalMutex);
	Triangle::replaceNeighbor(objective,replacement);
	neighborChanged.wakeAll();
}

ThreadSafeTriangle * ThreadSafeTriangle::getNeighborOposedToVertex(Vertex *v) const{
	QMutexLocker locker(&internalMutex);
	int index = -1;
	for(int i=0;i<3;i++){
		if(v->getId()==vertexs[i]->getId())
			index = i;
	}
	assert(index!=-1);
	return neighbors[index];
}

Angle ThreadSafeTriangle::getAngle(int i) const{
	QMutexLocker locker(&internalMutex);
	return Triangle::getAngle(i);
}

QMutex * ThreadSafeTriangle::getMutex(){
	return &mutex;
}

ThreadSafeTriangle *ThreadSafeTriangle::getNeighbor(int edge_index){
	while(true){
		internalMutex.lock();
		ThreadSafeTriangle *u = neighbors[edge_index];
		if(u!=0){
			if(u->getMutex()->tryLock()){
				internalMutex.unlock();
				return u;
			} else {
				neighborChanged.wait(&internalMutex);
				internalMutex.unlock();
			}
		} else {
			internalMutex.unlock();
			return u;
		}
	}
}

std::ostream& operator<< (std::ostream& out, const ThreadSafeTriangle& t){
	out << t.toString();
	return out;
}

